﻿using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Sasa.QualityTools.CodeAnalysis.Core.Views;
using Sasa.QualityTools.CodeAnalysis.Core.VisualStudio;
using Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.Views;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using Sasa.QualityTools.CodeAnalysis.Common;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.VisualStudio
{
    public class Ide : IIde
    {
        private FxCopIntegratorPackage package;


        public ISolution Solution
        {
            get
            {
                var dte = (DTE)((IServiceProvider)package).GetService(typeof(DTE));
                return new Solution(dte.Solution);
            }
        }

        public IEnumerable<IProjectItem> SelectedProjectItems
        {
            get
            {
                var result = new List<IProjectItem>();
                var dte = (DTE)((IServiceProvider)package).GetService(typeof(DTE));
                for (int i = 1; i <= dte.SelectedItems.Count; i++)
                {
                    result.Add(new ProjectItem(dte.SelectedItems.Item(i).ProjectItem));
                }
                return result;
            }
        }

        public FileVersionInfo VersionInfo
        {
            get
            {
                var dte = (DTE)((IServiceProvider)package).GetService(typeof(DTE));
                return FileVersionInfo.GetVersionInfo(dte.FullName);
            }
        }


        public Ide(FxCopIntegratorPackage package)
        {
            this.package = package;
        }


        public void NotifyInfo(string format, params object[] args)
        {
            MessageBox.Show(String.Format(CultureInfo.CurrentCulture, format, args), "Information", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
        }

        public void NotifyWarn(string format, params object[] args)
        {
            MessageBox.Show(String.Format(CultureInfo.CurrentCulture, format, args), "Warning", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
        }

        public void ShowError()
        {
            var errorList = (IVsErrorList)((IServiceProvider)package).GetService(typeof(SVsErrorList));
            ErrorHandler.ThrowOnFailure(errorList.BringToFront());
        }

        public bool Checkout(string path)
        {
            var dte = (DTE)((IServiceProvider)package).GetService(typeof(DTE));
            var scc = dte.SourceControl;
            if (!scc.IsItemUnderSCC(path) || scc.IsItemCheckedOut(path))
            {
                return false;
            }
            return scc.CheckOutItem(path);
        }

        public ICodeInspectionResultView FindCodeInspectionResultView()
        {
            return FindToolWindowPane<CodeInspectionResultWindowPane>();
        }

        public ICodeMetricsCalculationResultView FindCodeMetricsCalculationResultView()
        {
            return FindToolWindowPane<CodeMetricsCalculationResultWindowPane>();
        }

        public IRuleDetailView FindRuleDetailView()
        {
            return FindToolWindowPane<RuleDetailWindowPane>();
        }

        public T FindToolWindowPane<T>()
            where T : ToolWindowPane
        {
            var window = package.FindToolWindow(typeof(T), 0, true);
            if ((null == window) || (null == window.Frame))
            {
                var message = Text.Format("Failed to show the window pane '{0}'.", typeof(T).FullName);
                throw new NotSupportedException(message);
            }
            return (T)window;
        }

        public T ShowToolWindowPane<T>()
            where T : ToolWindowPane
        {
            var window = FindToolWindowPane<T>();
            var frame = (IVsWindowFrame)window.Frame;
            ErrorHandler.ThrowOnFailure(frame.Show());
            return (T)window;
        }

        public void Navigate(string url)
        {
            if (package.GeneralOption.UseExternalWebBrowser)
            {
                System.Diagnostics.Process.Start(url);
            }
            else
            {
                var dte = (DTE)((IServiceProvider)package).GetService(typeof(DTE));
                dte.ItemOperations.Navigate(url, vsNavigateOptions.vsNavigateOptionsNewWindow);
            }
        }
    }
}
